import java.util.PriorityQueue;
import java.util.concurrent.PriorityBlockingQueue;

class MyTimerTask implements Comparable<MyTimerTask> {
    private long time ;
    private Runnable runnable;
    public long getTime(){
        return time;
    }
    public MyTimerTask(Runnable runnable , long time){
        this.runnable = runnable;
        this.time = time + System.currentTimeMillis();
    }
    @Override
    public int compareTo(MyTimerTask o) {
        return (int)(this.time - o.time);
    }
    public void run(){
        runnable.run();
    }
}
class MyTimer{
    //先设定一个线程
    Thread t = null;
    //设定一个优先级队列将任务放置于优先级队列中
    //看到优先级队列其元素要实现Comparable接口,有程序员决定依据哪一个变量排序,升序还是降序
    private PriorityQueue<MyTimerTask> priorityQueue = new PriorityQueue<>();
    //实现schedule方法,实际上就是通过schedule往优先级队列中添加元素
    private Object locker = new Object();

    public void schedule(Runnable runnable , long time){
        synchronized (locker){
            MyTimerTask myTimerTask = new MyTimerTask(runnable,time);
            priorityQueue.offer(myTimerTask);
            locker.notify();
        }
    }
    public void cancel(){
        t.interrupt();
    }
    public MyTimer() {
        //首先我们需要先实例化线程扫描队列,根据时间来决定是否需要完成任务
        t = new Thread(() ->{
                //线程内部需要对优先级队列进行扫描
            while (!t.isInterrupted()) {
                try {
                    synchronized (locker) {
                        //如果优先级队列为空,则进行wait
                        while (priorityQueue.isEmpty()) {
                            locker.wait();
                        }
                        MyTimerTask task = priorityQueue.peek();
                        long current = System.currentTimeMillis();
                        if (task.getTime() <= current) {
                            priorityQueue.poll();
                            task.run();
                        } else {
                            locker.wait(task.getTime() - current);
                        }
                    }
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
        });
        //***让线程启动
        t.start();
    }
}
public class TestTimer {
    public static void main(String[] args) throws InterruptedException {
        //我们先按照Timer方法将结构写出,可以发现我们需要两个类MyTimer和MyTimerTask
        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("1000");
            }
        } , 3000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("3000");
            }
        } , 2000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("2000");
            }
        } , 1000);
        System.out.println(" hello man");
        Thread.sleep(5000);
        myTimer.cancel();
    }
    }
